const ws = require('nodejs-websocket');

class Server {
    constructor() {
        // 存储 collection
        this.store = {};
        this.server = ws.createServer((connection) => {
            let clientId = null;
            connection.on('text', (result) => {
                console.log('text', result);
                const data = JSON.parse(result);
                if (data.type === 'subscribe') {
                    console.log('收到订阅请求', data.name, data.clientId);
                    this.publish(connection, data.name, data.clientId);
                    clientId = data.clientId;
                } else if (data.type === 'change') {
                    console.log('收到更新请求', data.name, data.clientId, data.data.type);
                    this.__broadcast(data.name, data.clientId, data.data);
                }
            });
            connection.on('connect', (code) => {
                console.log('开启连接', code);
            });
            connection.on('close', (code) => {
                this.unPublish(clientId);
                console.log('关闭连接', code);
            });
            connection.on('error', (code) => {
                try {
                    connection.close();
                    this.unPublish(clientId);
                } catch (error) {
                    console.log('close异常', error);
                }
                console.log('异常关闭', code);
            });
        });
    }

    run() {
        this.server.listen(9998);
    }

    publish(connection, name, clientId) {
        if (!this.store[name]) {
            // 使用数组存储所有订阅请求
            this.store[name] = [];
        }

        this.store[name].push({
            clientId,
            name,
            connection,
        });

        return this;
    }

    unPublish(clientId) {
        Object.keys(this.store)
            .forEach((name) => {
                const s = this.store[name];
                for (let i = 0; i < s.length; i++) {
                    if (s[i].clientId === clientId) {
                        s.splice(i, 1);
                        break;
                    }
                }
                console.log(name, 'sub count', this.store[name].length);
            });
    }

    /**
     * 广播请求
     * @param {*} name 订阅名
     * @param {*} from 来源client的id
     * @param {*} action 更新事件对象
     */
    __broadcast(name, from, action) {
        console.log('broadcast', name, from, action);
        if (this.store[name]) {
            this.store[name].forEach((o) => {
                if (o.clientId === from) {
                    console.log('来源过滤', o.clientId, from);
                    return false;
                }
                o.connection.sendText(JSON.stringify(action));
                return false;
            });
        }
    }
}

module.exports = Server;
